package com.items.TreeUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


public class ITreeUtilImpl<E,R> implements ITreeUtil<E,R> {

    /**
     * 获取父节点的方法
     */
    private Function<E, R> parentFunc;
    /**
     * 获取节点的方法
     */
    private Function<E, R> codeFunc;
    /**
     * 设置子节点的方法
     */
    private Customer<E> consumer;
    /**
     * 获取子组织列表的方法
     */
    private Function<E, List<E>> listFunc;
    /**
     * 源数据
     */
    private List<E> boList;

    public ITreeUtilImpl(){}

    public ITreeUtilImpl(List<E> list) {
        this.boList = list;
    }

    public List<E> getBoList() {
        return boList;
    }

    public void setBoList(List<E> boList) {
        this.boList = boList;
    }

    public void setListFunc(Function<E, List<E>> listFunc) {
        this.listFunc = listFunc;
    }

    public void setParentFunc(Function<E, R> parentFunc) {
        this.parentFunc = parentFunc;
    }

    public void setCodeFunc(Function<E, R> codeFunc) {
        this.codeFunc = codeFunc;
    }

    public void setConsumer(Customer<E> consumer) {
        this.consumer = consumer;
    }

    @Override
    public List<E> getTreeList(final List<E> eList) {
        final List<E> list = new ArrayList<>();
        for (E e : eList) {
            list.add(this.getTree(e, boList));
        }
        return list;
    }

    @Override
    public E getTree(E e, List<E> boList) {
        //所有节点
        final Map<R, E> map = new HashMap<>();
        final Map<R, List<E>> eMap = new HashMap<>();
        for (E bo : boList) {
            R ParentCode = parentFunc.apply(bo);
            R code = codeFunc.apply(bo);
            if (!eMap.containsKey(ParentCode)) {
                eMap.put(ParentCode, new ArrayList<>());
            }
            map.put(code, bo);
            eMap.get(ParentCode).add(bo);
        }
//        e = getTreeGen(map, e);
        this.getSubordinate(eMap, e, listFunc);
        return e;
    }


    private void getSubordinate(Map<R, List<E>> boMap, E e, Function<E, List<E>> listFunc) {
        R code = codeFunc.apply(e);
        if (boMap.containsKey(code)) {   // 从map中查询子组织列表
            consumer.access(e, boMap.get(code));     //设置bo的子组织
            for (E e1 : listFunc.apply(e)) {    // 遍历子组织列表
                this.getSubordinate(boMap, e1, listFunc);
            }
        }

    }

    @Override
    public E getTreeGen(final Map<R, E> map, E bo) {

        while (true) {
            R ParentCode = parentFunc.apply(bo);
            if (ParentCode == null || ParentCode == "") {
                break;
            }
            final E e = map.get(ParentCode);
            if (e != null) {
                bo = e;
            } else {
                break;
            }
        }
        return bo;
    }
}
